Imports System.Xml
Imports ToDoList.Navigation
Imports ToDoList.Usecases

Namespace Views
  Public Class ToDoListForm
    Implements IManageTodoListNavigation
    Implements ISelectToDoListNavigation

    Private mViewUsecase As ManageTodoListUsecase
    Private mSelectUsecase As SelectTodoListUsecase

    'state about collapsing elements or not
    Private mTreeState As TreeNodeExpandedState

    ''' <summary>
    ''' application container should pass the usecases
    ''' for this view by this method
    ''' </summary>
    Public Sub Usecases(ByVal selectUsecase As SelectTodoListUsecase, ByVal viewUsecase As ManageTodoListUsecase)
      mViewUsecase = viewUsecase
      mSelectUsecase = selectUsecase
    End Sub

    ''' <summary>
    ''' present choice to user: either make a new list or open
    ''' from disk
    ''' </summary>
    Public Sub PresentSelectionChoice() Implements ISelectToDoListNavigation.PresentSelectionChoice
      'that's what this dialog is all about :)
      Me.ShowDialog()
    End Sub

    ''' <summary>
    ''' Handle menu 'open' click
    ''' </summary>
    Private Sub mnuOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuOpen.Click
      FileSelector()
    End Sub

    ''' <summary>
    ''' handle "new" click (from menu)
    ''' </summary>
    Private Sub mnuNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuNew.Click
      mSelectUsecase.RequestNew()
    End Sub

    ''' <summary>
    ''' Show the OpenFileDialog and let the user choose a file from the
    ''' device to open.
    ''' </summary>
    Public Sub FileSelector()
      If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

        'return file to the usecase
        mSelectUsecase.FileToOpenSelected(OpenFileDialog1.FileName)
      End If
    End Sub

    ''' <summary>
    ''' ask user to pick a filename
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub AskFilename() Implements Navigation.ISelectToDoListNavigation.AskFilename
      If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
        'return filename to the usecase
        mSelectUsecase.FileNameToSaveEntered(SaveFileDialog1.FileName)
      End If
    End Sub

    ''' <summary>
    ''' List all tasks from the given file
    ''' </summary>
    ''' <param name="todolist">tasklist</param>
    Public Sub List(ByVal todoList As Model.Todolist, ByVal itemToSelect As Model.Task) Implements IManageTodoListNavigation.List
      saveTreeState()

      Me.Text = todoList.ProjectName
      TreeView.Nodes.Clear()

      'fill the tree. state is restored during filling
      For Each lTask As Model.Task In todoList.Tasks
        showTaskNodeInTree(lTask, TreeView.Nodes, itemToSelect)
      Next

      'enable buttons 
      mnuSave.Enabled = True
      mnuSaveAs.Enabled = True
      btnNewTask.Visible = True
      btnNewSubTask.Visible = True
      mnuDetails.Enabled = True
      lblStart.Visible = False

      'set focus on tree
      TreeView.Focus()

    End Sub

    ''' <summary>
    ''' Show 1 taks node in the tree + trigger its subelements recursively
    ''' </summary>
    ''' <param name="task">Task to be shown</param>
    ''' <param name="addToCollection">The collection to add the node to (=position in the tree)</param>
    Private Sub showTaskNodeInTree(ByVal task As Model.Task, ByVal addToCollection As TreeNodeCollection, ByVal itemToSelect As Model.Task)

      Dim lNode As New TreeNode(task.Title)
      lNode.Tag = task.Id
      lNode.Checked = (task.PercentDone = 100)
      addToCollection.Add(lNode)

      'add subnodes as well
      For Each lSubTask As Model.Task In task.Tasks
        showTaskNodeInTree(lSubTask, lNode.Nodes, itemToSelect)
      Next

      'expand node if necessary
      If mTreeState.IsExpanded(task.Id) Then
        lNode.Expand()
      End If

      'select node if necessary
      If task Is itemToSelect Then
        TreeView.SelectedNode = lNode
      End If

    End Sub

    ''' <summary>
    ''' Save state of the tree to restore the selected item afterwards
    ''' </summary>
    Private Sub saveTreeState()
      Dim lRootState As New TreeNodeExpandedState()
      For Each lNode As TreeNode In TreeView.Nodes
        'treenodeexpandedstate adds child nodes recursively
        lRootState.ChildList.Add(New TreeNodeExpandedState(lNode))
      Next
      mTreeState = lRootState
    End Sub

    ''' <summary>
    ''' Show a message to the user
    ''' </summary>
    ''' <param name="message">the message to show</param>
    Public Sub Message(ByVal message As String) Implements ISelectToDoListNavigation.Message
      MsgBox(message)
    End Sub

    ''' <summary>
    ''' handle details click
    ''' </summary>
    Private Sub mnuDetails_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuDetails.Click
      If getSelectedTask() = 0 Then
        MsgBox("Please select a task from the list")
      Else
        mViewUsecase.RequestDetails(getSelectedTask())
      End If
    End Sub

    ''' <summary>
    ''' handle new click
    ''' </summary>
    Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewTask.Click
      Dim lContextTaskid As Integer = getSelectedTask()
      mViewUsecase.RequestNewTask(lContextTaskid)
    End Sub

    ''' <summary>
    ''' handle new sub click
    ''' </summary>
    Private Sub btnSub_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewSubTask.Click
      Dim lContextTaskId As Integer = getSelectedTask()
      mViewUsecase.RequestSubTask(lContextTaskId)
    End Sub

    Private Function getSelectedTask() As Integer
      Dim lSelectedTaskid As Integer = 0
      If TreeView.SelectedNode IsNot Nothing Then
        lSelectedTaskid = CInt(TreeView.SelectedNode.Tag)
      End If
      Return lSelectedTaskid
    End Function

    ''' <summary>
    ''' handle exit click
    ''' </summary>
    Private Sub mnuExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuExit.Click
      Me.Close()
    End Sub

    ''' <summary>
    ''' handle save click
    ''' </summary>
    Private Sub mnuSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuSave.Click
      mSelectUsecase.RequestSave()
    End Sub

  End Class
End Namespace

